package logic

import (
	"context"
	"mldong/api/auth"
	userApi "mldong/api/user"
	"mldong/internal/consts"
	dao "mldong/internal/modules/sys/dao"
	"mldong/internal/modules/sys/entity"
	"mldong/internal/modules/sys/enum"
	service "mldong/internal/modules/sys/service"
	"mldong/utility"
	"strings"
	"time"

	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/golang-jwt/jwt/v5"
	"github.com/jinzhu/copier"
)

func init() {
	// 注册服务实现
	utility.Register(service.UserServiceType, NewUserLogic())
}

type UserLogic struct {
	userDao     *dao.UserDao
	userRoleDao *dao.UserRoleDao
}

// 保存用户接口实现
func (logic *UserLogic) Save(ctx context.Context, req *userApi.SaveReq) (res bool, err error) {
	unique := utility.CheckUnique(logic.userDao.Model(nil), "userName", req.UserName, nil, "用户名已存在")
	if unique != nil {
		return false, unique
	}
	unique = utility.CheckUnique(logic.userDao.Model(nil), "mobilePhone", req.MobilePhone, nil, "手机号已存在")
	if unique != nil {
		return false, unique
	}
	var user = entity.User{}
	err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {

		// 1. 将req对象赋值给user
		// 2. 设置id===>雪花算法
		// 3. 设置salt===>随机字符串
		// 4. 设置password===>md5加密
		// 5. 创建时间/创建人/更新时间/修改人等信息设置===>自动
		// 6. 保存到数据库
		req.ID = nil
		// 将req对象赋值给user
		copier.Copy(&user, &req)
		user.AdminType = &enum.ADMIN_TYPE_COMMON_ADMIN.Code
		// 插入sys_user表
		user, err = logic.userDao.Insert(user, tx)
		if err != nil {
			return err
		}
		// 判断req.roleIdList是否为空
		if len(req.RoleIdList) > 0 {
			for _, roleId := range req.RoleIdList {
				var userRole = entity.UserRole{}
				userRole.UserId = user.ID
				userRole.RoleId = roleId
				// 保存用户角色关系
				// 插入sys_user_role
				var _, urErr = logic.userRoleDao.Insert(userRole, tx)
				if urErr != nil {
					err = urErr
					return err
				}
			}
		}
		return nil
	})
	return user.ID != nil, err
}

// 修改用户接口实现
func (logic *UserLogic) Update(ctx context.Context, req *userApi.UpdateReq) (res bool, err error) {
	unique := utility.CheckUnique(logic.userDao.Model(nil), "userName", req.UserName, req.ID, "用户名已存在")
	if unique != nil {
		return false, unique
	}
	unique = utility.CheckUnique(logic.userDao.Model(nil), "mobilePhone", req.MobilePhone, req.ID, "手机号已存在")
	if unique != nil {
		return false, unique
	}
	var user = entity.User{}
	// 将req对象赋值给user
	copier.Copy(&user, &req)
	var count int64
	count, err = logic.userDao.UpdateById(user, nil)
	if err != nil {
		return false, err
	}
	return count > 0, err
}

// 删除用户接口实现
func (logic *UserLogic) Remove(ctx context.Context, ids []string) (res bool, _ error) {
	// 遍历ids
	// for _, id := range ids {
	// 	userDao.DeleteById(id)
	// }
	var count, err = logic.userDao.DeleteByIds(ids)
	if err != nil {
		return false, err
	}
	if count == 0 {
		return false, err
	}
	return true, err
}

// 根据ID获取用户信息
func (logic *UserLogic) Detail(ctx context.Context, id string) (res userApi.UserVO, err error) {
	var userVO = userApi.UserVO{}
	var user entity.User
	user, err = logic.userDao.GetById(id)

	// 将user对象赋值给userVO
	copier.Copy(&userVO, &user)
	var userRoleList, urErr = logic.userRoleDao.GetByUserId(id)
	if urErr != nil {
		return userVO, err
	}
	userVO.RoleIds = ""
	for _, userRole := range userRoleList {
		userVO.RoleIds = userVO.RoleIds + *userRole.RoleId + ","
	}
	// 去掉最后一个逗号
	if userVO.RoleIds == "" {
		return userVO, err
	}
	userVO.RoleIds = userVO.RoleIds[:len(userVO.RoleIds)-1]
	// 服务之间相互依赖，需要使用 utility 获取服务实例
	// roleService := utility.MustResolve(service.RoleServiceType).(service.IRoleService)
	return userVO, err
}

// 分页查询用户接口实现
func (logic *UserLogic) Page(ctx context.Context, req *userApi.PageReq) (res userApi.UserPageVO, err error) {
	// 处理分页参数nil值
	utility.HandlePageParam(&req.PageParam)
	// 传递以m_开头的查询参数
	req.QueryParamMap = utility.GetQueryParamMap(ctx)
	users, total, err := logic.userDao.Page(*req.PageNum, *req.PageSize, func(model *gdb.Model) *gdb.Model {
		model = utility.BuildQuery(req.PageParam, model)
		if len(req.InUserIdList) > 0 {
			model = model.WhereIn("t.id", req.InUserIdList)
		}
		if len(req.NotInUserIdList) > 0 {
			model = model.WhereNotIn("t.id", req.NotInUserIdList)
		}
		model = model.Where("t.admin_type<>?", enum.ADMIN_TYPE_SUPER_ADMIN.Code)
		return model
	})
	userPage := userApi.UserPageVO{
		Rows: users,
	}
	userPage.PageNum = *req.PageNum
	userPage.PageSize = *req.PageSize
	userPage.RecordCount = total
	// 计算 TotalPage
	if *req.PageSize > 0 {
		userPage.TotalPage = (total + *req.PageSize - 1) / *req.PageSize
	} else {
		userPage.TotalPage = 0 // 如果 PageSize 为 0，则 TotalPage 为 0
	}
	return userPage, err
}

// 重置密码
func (logic *UserLogic) ResetPassword(ctx context.Context, ids []string) (res bool, err error) {
	/// TODO: 业务逻辑
	return true, nil
}

// 登录
func (logic *UserLogic) Login(ctx context.Context, req *auth.LoginReq) (res auth.LoginVO, err error) {
	// 1.根据用户名查询用户信息
	var user entity.User
	user, err = logic.userDao.GetByUserName(req.UserName)
	if err != nil {
		return res, gerror.New("用户名或密码不正确")
	}
	// 2.校验密码是否正确
	encryptedPassword := gmd5.MustEncryptString(req.Password + *user.Salt)

	if *user.Password != encryptedPassword {
		return res, gerror.New("用户名或密码不正确")
	}
	rbacService := utility.MustResolve(service.RbacServiceType).(service.IRbacService)
	RoleIdList, err := rbacService.GetRoleIdsByUserId(ctx, *user.ID)
	if err != nil {
		return res, err
	}
	PermCodes := []string{}
	if *user.AdminType == enum.ADMIN_TYPE_SUPER_ADMIN.Code {
		PermCodes = append(PermCodes, consts.SuperAdminAuthKey)
	} else {
		for _, roleId := range RoleIdList {
			menuCodes, err := rbacService.GetMenuCodesByRoleId(ctx, roleId)
			if err != nil {
				return res, err
			}
			PermCodes = append(PermCodes, menuCodes...)
		}
	}
	// 3.生成token和refreshToken
	uc := &auth.LoginUserVO{
		UserId:     *user.ID,
		UserName:   *user.UserName,
		AdminType:  *user.AdminType,
		RoleIdList: RoleIdList,
		RoleIds:    strings.Join(RoleIdList, ","),
		SuperAdmin: *user.AdminType == enum.ADMIN_TYPE_SUPER_ADMIN.Code,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(6 * time.Hour)),
		},
		PermCodes: PermCodes,
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, uc)
	res.Token, err = token.SignedString([]byte(consts.JwtKey))
	if err != nil {
		return res, err
	}
	res.UserId = *user.ID
	return res, nil
}
func (logic *UserLogic) PermCode(ctx context.Context, userId string) (res []string, err error) {
	user, err := logic.userDao.GetById(userId)
	if err != nil {
		return res, err
	}
	PermCodes := []string{}

	if *user.AdminType == enum.ADMIN_TYPE_SUPER_ADMIN.Code {
		PermCodes = append(PermCodes, consts.SuperAdminAuthKey)
	} else {
		rbacService := utility.MustResolve(service.RbacServiceType).(service.IRbacService)
		RoleIdList, err := rbacService.GetRoleIdsByUserId(ctx, *user.ID)
		if err != nil {
			return res, err
		}
		for _, roleId := range RoleIdList {
			menuCodes, err := rbacService.GetMenuCodesByRoleId(ctx, roleId)
			if err != nil {
				return res, err
			}
			PermCodes = append(PermCodes, menuCodes...)
		}
	}
	return PermCodes, nil
}
func NewUserLogic() service.IUserService {
	return &UserLogic{
		userDao:     dao.NewUserDao(),
		userRoleDao: dao.NewUserRoleDao(),
	}
}
